﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;

namespace PickGold.Generic
{
	/// <summary>
	/// 实现列表数据结构，非线程安全类型。
	/// </summary>
	/// <typeparam name="T">元素类型。</typeparam>
	[Serializable]
	public class ListTable<T>
	{
		/// <summary>
		/// 类型默认值；多数情况下为空。
		/// </summary>
		[NonSerialized]
		private static readonly T @default = default(T);
		[NonSerialized]
		private static readonly EqualityComparer<T> DefaultComparer = EqualityComparer<T>.Default;

		/// <summary>
		/// 开始指针索引。
		/// </summary>
		private int _Head;
		/// <summary>
		/// 结尾指针索引。
		/// </summary>
		private int _Tail;
		/// <summary>
		/// 有效元素总数。
		/// </summary>
		private int _Count;
		/// <summary>
		/// 元素数组。
		/// </summary>
		private T[] _Items;

		/// <summary>
		/// 构造一对象，默认要存储的数量为 255 个。
		/// </summary>
		public ListTable() : this(0) { }
		/// <summary>
		/// 构造一对象。
		/// </summary>
		/// <param name="capacity">指定要存储的数量，默认为 255 个。</param>
		public ListTable(int capacity)
		{
			if (capacity <= 0)
				capacity = byte.MaxValue;
			this._Items = new T[capacity];
		}

		/// <summary>
		/// 设置或获取相对于开始位置指定索引处的对象。
		/// </summary>
		/// <param name="index">相对于开始位置的指定索引。</param>
		/// <returns>相对于开始位置指定索引处的对象。</returns>
		public T this[int index]
		{
			set
			{
				var item = this._Items[(this._Head + index) % this._Items.Length];
				this._Items[(this._Head + index) % this._Items.Length] = value;
				if (DefaultComparer.Equals(item, @default) && !DefaultComparer.Equals(value, @default))
				{
					this._Count++;
					return;
				}

				if (!DefaultComparer.Equals(item, @default) && DefaultComparer.Equals(value, @default))
					this._Count--;
			}
			get
			{
				return this._Items[(this._Head + index) % this._Items.Length];
			}
		}

		/// <summary>
		/// 返回内部存在的元素数量；
		/// </summary>
		public int Count
		{
			get
			{
				return this._Count;
			}
		}

		/// <summary>
		/// 返回内部可容纳的元素数量。
		/// </summary>
		public int Capacity
		{
			get
			{
				return this._Items.Length;
			}
		}

		/// <summary>
		/// 返回是否存在数据。
		/// </summary>
		public bool HasItems
		{
			get
			{
				if (this._Head == this._Tail && DefaultComparer.Equals(this._Items[this._Head], @default))
					return false;

				return true;
			}
		}

		/// <summary>
		/// 将对象添加到结尾处。
		/// </summary>
		/// <param name="item">要添加到结尾处的对象</param>
		/// <returns>原位置处的对象，可以此确定是否有对象被覆盖。</returns>
		[Obsolete("未实现。", true)]
		public T Push(T item)
		{
			throw new NotSupportedException();
			//if (DefaultComparer.Equals(item, @default))
			//    return item;

			//var head = this._Head;//简单的线程互斥变量。
			//var tail = this._Tail;//简单的线程互斥变量。
			//if (this._Tail == tail && tail == head)//如果当前指针重叠。
			//    this._Tail = (tail + this._Items.Length - 1) % this._Items.Length;//结尾指针后移。
			//if (this._Head == head)
			//    this._Head = (head + this._Items.Length - 1) % this._Items.Length;//开始指针后移。
			//if (DefaultComparer.Equals(this._Items[head], @default))
			//    this._Count++;
			//var old = this._Items[head];
			//this._Items[head] = item;
			//if (DefaultComparer.Equals(old, @default))
			//    return item;

			//return old;
		}

		/// <summary>
		/// 移除并返回位于结尾处的对象。
		/// </summary>
		/// <param name="keep">是否保留对象，注意：即使保留对象，结尾处指针也会移动，如果不想移动指针，请使用 Peek 方法。</param>
		/// <returns>位于结尾处的对象。</returns>
		[Obsolete("未实现。", true)]
		public T Pop(bool keep)
		{
			throw new NotSupportedException();
			//var head = this._Head;//简单的线程互斥变量。
			//var tail = this._Tail;//简单的线程互斥变量。
			//for (; ; )
			//{
			//    var next = tail;
			//    if (this._Tail == tail)
			//    {
			//        if (this._Head == head && head == tail && DefaultComparer.Equals(this._Items[head], @default))
			//        {
			//            head = (head + this._Items.Length - 1) % this._Items.Length;
			//            this._Head = head;
			//        }
			//        tail = (tail + this._Items.Length - 1) % this._Items.Length;
			//        this._Tail = tail;
			//    }
			//    var item = this._Items[tail];
			//    if (head == tail || DefaultComparer.Equals(item, @default))
			//    {
			//        if (this._Tail == tail)
			//            continue;

			//        return item;
			//    }

			//    if (keep)
			//        return item;

			//    this._Items[next] = @default;
			//    this._Count--;
			//    return item;
			//}
		}

		/// <summary>
		/// 将对象添加到开始处。
		/// </summary>
		/// <param name="item">要添加到开始处的对象</param>
		/// <returns>原位置处的对象，可以此确定是否有对象被覆盖。</returns>
		public T Enqueue(T item)
		{
			if (DefaultComparer.Equals(item, @default))
				return item;

			var head = this._Head;//简单的线程互斥变量。
			var tail = this._Tail;//简单的线程互斥变量。
			if (DefaultComparer.Equals(this._Items[tail], @default))
				this._Count++;
			var old = this._Items[tail];
			if (this._Head == head && head == tail && !DefaultComparer.Equals(old, @default))//指针重叠，并开始指针处不为空。
				this._Head = (head + 1) % this._Items.Length;//前进开始指针。
			if (this._Tail == tail)
				this._Tail = (tail + 1) % this._Items.Length;//前进结尾指针。
			this._Items[tail] = item;
			if (DefaultComparer.Equals(old, @default))
				return item;

			return old;
		}

		/// <summary>
		/// 移除并返回位于开始处的对象。
		/// </summary>
		/// <param name="keep">是否保留对象，注意：即使保留对象，开始处指针也会移动，如果不想移动指针，请使用 Peek 方法。</param>
		/// <returns>位于开始处的对象。</returns>
		public T Dequeue(bool keep)
		{
			var head = this._Head;//简单的线程互斥变量。
			var tail = this._Tail;//简单的线程互斥变量。
			for (var i = head; ; i++)
			{
				head = i % this._Items.Length;
				var item = this._Items[head];
				if (head == tail && (i != head || DefaultComparer.Equals(item, @default)))
				{
					if (keep || DefaultComparer.Equals(item, @default))
						return item;

					this._Items[head] = @default;
					this._Count--;
					return item;
				}

				var previous = head;
				if (this._Head == head)
				{
					head = (head + 1) % this._Items.Length;
					this._Head = head;
				}
				if (DefaultComparer.Equals(item, @default))
				{
					if (this._Head == head)
						continue;

					return item;
				}

				if (keep)
					return item;

				this._Items[previous] = @default;
				this._Count--;
				return item;
			}
		}

		/// <summary>
		/// 返回位于开始处的对象但不将其移除。
		/// </summary>
		/// <returns>位于开始处的对象</returns>
		[Obsolete("未实现。", true)]
		public T Peek()
		{
			throw new NotSupportedException();
			//var head = this._Head;//简单的线程互斥变量。
			//var tail = this._Tail;//简单的线程互斥变量。
			//for (; ; )
			//{
			//    var item = this._Items[head];
			//    if (head == tail || !DefaultComparer.Equals(item, @default))
			//        return item;

			//    if (this._Head != head)
			//        return item;

			//    head = (head + 1) % this._Items.Length;
			//    this._Head = head;
			//}
		}

		/// <summary>
		/// 返回位于开始处指定偏移量的对象但不将其移除。
		/// </summary>
		/// <param name="offset">位于开始处的偏移量</param>
		/// <returns>位于开始处指定偏移量的对象</returns>
		[Obsolete("未实现。", true)]
		public T Peek(int offset)
		{
			throw new NotSupportedException();
			//if (offset == 0)
			//    return this.Peek();

			//if (offset > 0)
			//    return this.PeekFoot(offset);

			//return this.PeekTop(-offset);
		}

		[Obsolete("未实现。", true)]
		private T PeekTop(int offset)
		{
			throw new NotSupportedException();
			//var head = this._Head;//简单的线程互斥变量。
			//var tail = this._Tail;//简单的线程互斥变量。
			//offset--;
			//for (; ; )
			//{
			//    if (tail == head)
			//        return @default;

			//    tail = (tail + this._Items.Length - 1) % this._Items.Length;
			//    var item = this._Items[tail];
			//    if (DefaultComparer.Equals(item, @default))
			//        continue;

			//    if (offset == 0)
			//        return item;

			//    offset--;
			//}
		}

		[Obsolete("未实现。", true)]
		private T PeekFoot(int offset)
		{
			throw new NotSupportedException();
			//var head = this._Head;//简单的线程互斥变量。
			//var tail = this._Tail;//简单的线程互斥变量。
			//for (; ; )
			//{
			//    var item = this._Items[head];
			//    if (head == tail)
			//        return item;

			//    if (DefaultComparer.Equals(item, @default))
			//        continue;

			//    if (offset == 0)
			//        return item;

			//    offset--;
			//    head = (head + 1) % this._Items.Length;
			//}
		}

		/// <summary>
		/// 移除指定的对象。
		/// </summary>
		/// <param name="item">要移除的对象</param>
		/// <returns>如果删除成功，则返回 True；否则返回 False ；</returns>
		[Obsolete("未实现。", true)]
		public bool Remove(T item)
		{
			throw new NotSupportedException();
			//var comparer = DefaultComparer;
			//if (DefaultComparer.Equals(item, @default))
			//    return false;

			//var index = this._Head;
			//var head = this._Head;//简单的线程互斥变量。
			//var tail = this._Tail;//简单的线程互斥变量。
			//for (var i = index; ; i++)
			//{
			//    index = i % this._Items.Length;
			//    if (DefaultComparer.Equals(this._Items[index], item))
			//    {
			//        this._Count--;
			//        this._Items[index] = @default;
			//        comparer = null;//在以下代码中，如果此对象为空表示比较成功。
			//        break;
			//    }

			//    if (index == tail)
			//        break;
			//}

			//if (head != index || head == tail)
			//{
			//    if (comparer == null)
			//        return true;

			//    return false;
			//}

			//for (; ; )
			//{
			//    if (this._Head != head)
			//        break;

			//    head = (head + 1) % this._Items.Length;
			//    this._Head = head;
			//    if (head == tail || !DefaultComparer.Equals(this._Items[head], @default))
			//        break;
			//}
			//if (comparer == null)
			//    return true;

			//return false;
		}

		/// <summary>
		/// 确定集合是否包含指定的对象。
		/// </summary>
		/// <param name="item">查找的对象。</param>
		/// <returns>如果对象存在，则返回 True；否则返回 False ；</returns>
		public bool Contains(T item)
		{
			var head = this._Head;//简单的线程互斥变量。
			var tail = this._Tail;//简单的线程互斥变量。
			for (var i = this._Head; ; i++)
			{
				head = i % this._Items.Length;
				if (DefaultComparer.Equals(this._Items[head], item))
					return true;

				if (head == tail && (i != head || DefaultComparer.Equals(this._Items[head], @default)))
					return false;
			}
		}

		/// <summary>
		/// 向目标数组拷贝元素。
		/// </summary>
		/// <param name="array">目标数组。</param>
		/// <param name="index">目标数组开始拷贝处索引。</param>
		/// <param name="count">向目标数组处拷贝的元素数量。</param>
		/// <returns>实际向目标数组处拷贝的元素数量。</returns>
		public int CopyTo(Array array, int index, int count)
		{
			var copy = 0;
			var head = this._Head;//简单的线程互斥变量。
			var tail = this._Tail;//简单的线程互斥变量。
			if (count <= 0 || count > array.Length)
				count = array.Length;
			for (var i = head; ; i++)
			{
				if (count == 0)
					break;

				head = i % this._Items.Length;
				var item = this._Items[head];
				if (DefaultComparer.Equals(item, @default))
					continue;

				array.SetValue(item, index + copy);
				copy++;
				count--;
				if (head == tail && (i != head || DefaultComparer.Equals(this._Items[head], @default)))
					break;
			}
			return copy;
		}

		/// <summary>
		/// 清除所有数据。
		/// </summary>
		public void Clear()
		{
			this._Head = 0;
			this._Tail = 0;
			this._Count = 0;
			this._Items = new T[this._Items.Length];
		}
	}
}
